package util.conversor;

import syntaxtree.And;
import syntaxtree.ArrayLength;
import syntaxtree.ArrayLookup;
import syntaxtree.Call;
import syntaxtree.Equal;
import syntaxtree.Exp;
import syntaxtree.False;
import syntaxtree.Identifier;
import syntaxtree.IdentifierExp;
import syntaxtree.IntegerLiteral;
import syntaxtree.LessThan;
import syntaxtree.Minus;
import syntaxtree.NewArray;
import syntaxtree.NewObject;
import syntaxtree.Not;
import syntaxtree.Plus;
import syntaxtree.This;
import syntaxtree.Times;
import syntaxtree.True;
import util.List;
import minijava.analysis.AnalysisAdapter;
import minijava.node.AAndExpression;
import minijava.node.AArraylengthExpression;
import minijava.node.AArraylookupExpression;
import minijava.node.ACallExpression;
import minijava.node.ACompExpression;
import minijava.node.AFalseExpression;
import minijava.node.AIdExpression;
import minijava.node.AIntliteralExpression;
import minijava.node.ALessExpression;
import minijava.node.AMinusExpression;
import minijava.node.ANewarrayExpression;
import minijava.node.ANewobjExpression;
import minijava.node.ANotExpression;
import minijava.node.ASumExpression;
import minijava.node.AThisExpression;
import minijava.node.ATimesExpression;
import minijava.node.ATrueExpression;
import minijava.node.PExpression;
import minijava.node.Token;

class ExpHandler extends AnalysisAdapter
{
	private Exp result;
	
	private ExpHandler()
	{
		super();
	}

	static Exp convert(PExpression node)
	{
		ExpHandler h = new ExpHandler();
		
		node.apply(h);
		
		return h.result;
	}
	
	public void caseAAndExpression(AAndExpression node)
	{
		Exp lhs = ExpHandler.convert(node.getExp1());
		Exp rhs = ExpHandler.convert(node.getExp2());

		Token t = node.getAnd();
		
		result = new And(t.getLine(), t.getPos(), lhs, rhs);
	}
	
	public void caseACompExpression(ACompExpression node)
	{
		Exp lhs = ExpHandler.convert(node.getExp1());
		Exp rhs = ExpHandler.convert(node.getExp2());

		Token t = node.getCompEqual();
		
		result = new Equal(t.getLine(), t.getPos(), lhs, rhs);
	}
	
	public void caseALessExpression(ALessExpression node)
	{
		Exp lhs = ExpHandler.convert(node.getExp1());
		Exp rhs = ExpHandler.convert(node.getExp2());

		Token t = node.getLess();
		
		result = new LessThan(t.getLine(), t.getPos(), lhs, rhs);
	}
	
	public void caseASumExpression(ASumExpression node)
	{
		Exp lhs = ExpHandler.convert(node.getExp1());
		Exp rhs = ExpHandler.convert(node.getExp2());

		Token t = node.getSum();
		
		result = new Plus(t.getLine(), t.getPos(), lhs, rhs);
	}
	
	public void caseAMinusExpression(AMinusExpression node)
	{
		Exp lhs = ExpHandler.convert(node.getExp1());
		Exp rhs = ExpHandler.convert(node.getExp2());

		Token t = node.getMinus();

		
		result = new Minus(t.getLine(), t.getPos(), lhs, rhs);
	}
	
	public void caseATimesExpression(ATimesExpression node)
	{
		Exp lhs = ExpHandler.convert(node.getExp1());
		Exp rhs = ExpHandler.convert(node.getExp2());

		Token t = node.getTimes();
		
		result = new Times(t.getLine(), t.getPos(), lhs, rhs);
	}

	public void caseATrueExpression(ATrueExpression node)
	{
		Token t = node.getTrue();
		
		result = new True(t.getLine(), t.getPos());
	}
	
	public void caseAFalseExpression(AFalseExpression node)
	{
		Token t = node.getFalse();
		
		result = new False(t.getLine(), t.getPos());
	}
	
	public void caseAThisExpression(AThisExpression node)
	{
		Token t = node.getThis();
		
		result = new This(t.getLine(), t.getPos());
	}
	
	public void caseANotExpression(ANotExpression node)
	{
		Exp e = ExpHandler.convert(node.getExpression());
		Token t = node.getNot();
		
		result = new Not(t.getLine(), t.getPos(), e);
	}
	
	public void caseAIntliteralExpression(AIntliteralExpression node)
	{
		Token t = node.getNumber();
		int v = Integer.valueOf(t.getText()).intValue();
		
		result = new IntegerLiteral(t.getLine(), t.getPos(), v); 
	}
	
	public void caseAIdExpression(AIdExpression node)
	{
		Token t = node.getId();
		String name = t.getText();
		
		Identifier id = new Identifier( t.getLine(), t.getPos(), name);
		result = new IdentifierExp(id.line, id.row, id);
	}
	
	public void caseACallExpression(ACallExpression node)
	{
		Exp object = ExpHandler.convert(node.getExp());
		List<Exp> actuals = ExpListHandler.convert(node.getExpList());
		Token method = node.getId();
		
		Identifier m = new Identifier(method.getLine(), method.getPos(), method.getText());
		
		result = new Call(m.line, m.row, object, m, actuals);
	}
	
	public void caseANewarrayExpression(ANewarrayExpression node)
	{
		Exp size = ExpHandler.convert(node.getExpression());
		Token t = node.getNew();
		
		result = new NewArray(t.getLine(), t.getPos(), size);
	}
	
	public void caseANewobjExpression(ANewobjExpression node)
	{
		Token t = node.getId();
		
		Identifier n = new Identifier(t.getLine(), t.getPos(), t.getText());
		
		result = new NewObject(n.line, n.row, n);
	}
	
	public void caseAArraylookupExpression(AArraylookupExpression node)
	{
		Exp arr = ExpHandler.convert(node.getExp1());
		Exp index = ExpHandler.convert(node.getExp2());
		Token t = node.getLeftbrack();
		
		result = new ArrayLookup(t.getLine(), t.getPos(), arr, index);
	}
	
	public void caseAArraylengthExpression(AArraylengthExpression node)
	{
		Exp arr = ExpHandler.convert(node.getExp());
		Token t = node.getLength();
                
		result = new ArrayLength(t.getLine(), t.getPos(), arr);
	}
}
